/**
 * @file ngmessagequeue.cpp
 * @author Suk Robert Koh (srkoh87z@gmail.com)
 */

#include "ngine/common/message/ngmessagequeue.h"

#ifdef WIN32
#define INIT(m)		InitializeCriticalSection(&m);
#define LOCK(m)		EnterCriticalSection(&m);
#define UNLOCK(m)	LeaveCriticalSection(&m);
#define DESTROY(m)	DeleteCriticalSection(&m);
#else
#define INIT(m)		pthread_mutex_init(&m, NULL);
#define LOCK(m)		pthread_mutex_lock(&m);
#define UNLOCK(m)	pthread_mutex_unlock(&m);
#define DESTROY(m)	pthread_mutex_destroy(&m);
#endif

/**
 * Default constructor for NGMessageQueue class
 */
NGMessageQueue::NGMessageQueue()
{
	// initialize mutex
	INIT(mutex);

	clear();
}

/**
 * Destructor for NGMessageQueue class
 */
NGMessageQueue::~NGMessageQueue()
{
	// destroy mutex
	DESTROY(mutex);
}

/**
 * Gets size of the queue
 *
 * @return	INT		Size of the queue
 */
int NGMessageQueue::size()
{
	int size;

	LOCK(mutex);
	size = (int) queue.size();
	UNLOCK(mutex);

	return size;
}

/**
 * Empties out the queue
 */
void NGMessageQueue::clear()
{
	LOCK(mutex);
	while(queue.size() > 0)
		queue.pop();
	UNLOCK(mutex);
}

/**
 * Removes the first element of the queue
 */
void NGMessageQueue::remove()
{
	LOCK(mutex);
	queue.pop();
	UNLOCK(mutex);
}

/**
 * Puts a message to the end of the queue
 *
 * @param	NGMessage *		Pointer to the message object
 */
void NGMessageQueue::push(NGMessage *msg)
{
	LOCK(mutex);
	queue.push(msg);
	UNLOCK(mutex);
}

/**
 * Gets the first message of the queue (the message gets removed from the queue)
 *
 * @return	NGMessage *		Pointer to the message object
 */
NGMessage *NGMessageQueue::pop()
{
	NGMessage *msg;

	LOCK(mutex);
	msg = queue.front();
	queue.pop();
	UNLOCK(mutex);

	return msg;
}

/**
 * Gets the first message of the queue (the message stays in the queue)
 *
 * @return	NGMessage *		Pointer to the message object
 */
NGMessage *NGMessageQueue::peek()
{
	NGMessage *msg;
	LOCK(mutex);
	msg = queue.front();
	UNLOCK(mutex);

	return msg;
}
